import socket
import time
from datetime import datetime
import mysql.connector

# 串口服务器配置
SERVER_IP = '10.1.230.72'
SERVER_PORT = 8002

db_config = {
    'host': '10.1.230.120',
    'user': 'root',
    'password': '123',
    'database': 'test02'
}

# 指令与位置映射
COMMAND_MAP = {
    '#+018983': '墩顶',
    '#+267456': '1/2跨',
    '#+017749': '1/4跨'
}

MAP_NUM ={
    '#+018983': '018983',
    '#+267456': '267456',
    '#+017749': '017749'
}
COMMANDS = list(COMMAND_MAP.keys())
NUM=list(MAP_NUM.keys())
COMMAND_INTERVAL = 1  # 指令间隔1秒
ROUND_INTERVAL = 5  # 每轮间隔5秒



# 数据缓存（用于中值和均值滤波）
data_buffer = {cmd: [] for cmd in COMMANDS}
BUFFER_SIZE = 5  # 缓存最近5组数据用于滤波


def limit_amplitude_filter(data, threshold):

    if not data or len(data) != 2:
        return None, None

    current_value, current_raw = data
    last_data = limit_amplitude_filter.last_data.get('default', (current_value, current_raw))

    try:
        # 值滤波
        filtered_value = last_data[0] if abs(current_value - last_data[0]) >= threshold else current_value
        # raw值滤波
        filtered_raw = last_data[1] if abs(current_raw - last_data[1]) >= threshold else current_raw

        # 更新上次数据
        limit_amplitude_filter.last_data['default'] = (current_value, current_raw)
        return filtered_value, filtered_raw

    except Exception as e:
        print(f'限幅滤波异常: {str(e)}')
        return current_value, current_raw


limit_amplitude_filter.last_data = {}


def median_filter(data_list):
    """中值滤波函数"""
    if not data_list:
        return None, None

    try:
        values = [x[0] for x in data_list if x[0] is not None]
        raws = [x[1] for x in data_list if x[1] is not None]

        values.sort()
        raws.sort()

        median_value = values[len(values) // 2] if values else None
        median_raw = raws[len(raws) // 2] if raws else None

        return median_value, median_raw

    except Exception as e:
        print(f'中值滤波异常: {str(e)}')
        return None, None


def mean_filter(data_list):
    """均值滤波函数"""
    if not data_list:
        return None, None

    try:
        sum_value = sum(x[0] for x in data_list if x[0] is not None)
        sum_raw = sum(x[1] for x in data_list if x[1] is not None)
        count_value = sum(1 for x in data_list if x[0] is not None)
        count_raw = sum(1 for x in data_list if x[1] is not None)

        mean_value = sum_value / count_value if count_value > 0 else None
        mean_raw = sum_raw / count_raw if count_raw > 0 else None

        return mean_value, mean_raw

    except Exception as e:
        print(f'均值滤波异常: {str(e)}')
        return None, None


def calculate_values(data):
    if len(data) != 13 or data[0] != 36:
        raise ValueError("无效的数据格式")

    X = data[1:]
    M = ((X[0] - 48) * 16 + (X[1] - 48) + (X[2] - 48) * 16 * 16 * 16 + (X[3] - 48) * 16 * 16) / 100
    M0 = ((X[4] - 48) * 16 + (X[5] - 48) + (X[6] - 48) * 16 * 16 * 16 + (X[7] - 48) * 16 * 16) / 100
    T = (((X[8] - 48) * 16 + (X[9] - 48) + (X[10] - 48) * 16 * 16 * 16 + (X[11] - 48) * 16 * 16) - 500) / 10

    return M, M0, T


def udp_client():
    global base_M, data_buffer, n
    connection = None
    n=0

    try:
        # 创建连接
        connection = mysql.connector.connect(**db_config)

        # 如果连接成功，打印提示信息
        if connection.is_connected():
            print("成功连接到数据库")
            cursor = connection.cursor()
            cursor.execute("SELECT * FROM sensor_info")
            result = cursor.fetchall()
            for row in result:
                print(row)
    except mysql.connector.Error as err:
        print(f"连接失败: {err}")

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    print(f"连接到UDP串口服务器 {SERVER_IP}:{SERVER_PORT}")
    print("按Ctrl+C停止程序")

    try:

        while True:
            current_round_results = {}
            # 存储基准M值
            base_M = None
            n = n + 1
            print(f"\n第{n}轮采集")

            for cmd in COMMANDS:

                position = COMMAND_MAP[cmd]
                sensor_id=MAP_NUM[cmd]
                # 发送指令
                print(f"\n{position}")
                sock.sendto(cmd.encode('utf-8'), (SERVER_IP, SERVER_PORT))

                # 接收数据
                sock.settimeout(1.0)
                try:

                    data, addr = sock.recvfrom(1024)
                    decimal_data = [int(byte) for byte in data]
                    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

                    print(f"原始数据: {decimal_data}")
                    print(f"采集时间: {current_time}")



                    if decimal_data is not None:
                        try:
                            M, M0, T = calculate_values(decimal_data)

                            # 设置基准值（使用墩顶数据）
                            if position == '墩顶' and base_M is None:
                                base_M = M
                                print(f"[{position}] 设置基准值: {base_M:.2f}mm")

                            if base_M is not None:
                                raw = M - base_M if base_M is not None else 0.0
                                print(f"原始值 : raw={raw:7.2f}mm")
                                cursor.execute(
                                    "INSERT INTO raw_data (sensor_id, raw_value, temp,timestamp) VALUES (%s, %s, %s, %s)",
                                    (sensor_id, raw, T, current_time)
                                )
                                raw_data_id = cursor.lastrowid
                                connection.commit()


                                if n>1 and data_buffer[cmd] is not None:
                                    # 1. 限幅滤波 (阈值设为0.5)
                                    filter_params=0.5
                                    alert_level=0
                                    alert_level_base=0
                                    threshold_value=46.05
                                    la_value, la_raw = limit_amplitude_filter((M, raw), filter_params)
                                    cursor.execute(
                                        """INSERT INTO filtered_data 
                                        (raw_data_id, sensor_id, filtered_value, filter_type, filter_params, receive_time) 
                                        VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                        (raw_data_id, sensor_id, la_raw, "限幅滤波", filter_params)
                                    )
                                    filtered_data_id = cursor.lastrowid
                                    connection.commit()
                                    print(f"限幅滤波 : raw={la_raw:7.2f}mm")
                                    if la_raw>threshold_value or la_raw<-threshold_value:
                                        threshold_value=threshold_value+1
                                        alert_level=alert_level+1

                                        if la_raw>threshold_value or la_raw<-threshold_value:
                                            threshold_value=threshold_value+1
                                            alert_level = alert_level + 1

                                            if la_raw>threshold_value or la_raw<-threshold_value:
                                                alert_level = alert_level + 1
                                        if alert_level== 1:
                                            print(f"\n橙色警报！")
                                        if alert_level == 2:
                                            print(f"\n红色警报！")
                                        if alert_level == 3:
                                            print(f"\n黄色警报！")
                                        cursor.execute(
                                            """INSERT INTO alert_records 
                                            (filtered_data_id, sensor_id, alert_level, alert_value, threshold_value, timestamp) 
                                            VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                            (filtered_data_id, sensor_id, alert_level, la_raw, threshold_value)
                                        )
                                        connection.commit()
                                        alert_level=alert_level_base


                                    # 2. 中值滤波
                                    md_value, md_raw = median_filter(data_buffer[cmd])
                                    if md_value:
                                        cursor.execute(
                                            """INSERT INTO filtered_data 
                                            (raw_data_id, sensor_id, filtered_value, filter_type, filter_params, receive_time) 
                                            VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                            (raw_data_id, sensor_id, md_raw, "中值滤波", len(data_buffer[cmd]))
                                        )
                                        filtered_data_id = cursor.lastrowid
                                        connection.commit()
                                        print(f"中值滤波 :raw={md_raw:7.2f}mm")
                                        if md_raw > threshold_value or md_raw < -threshold_value:
                                            threshold_value = threshold_value + 1
                                            alert_level = alert_level + 1

                                            if md_raw > threshold_value or md_raw < -threshold_value:
                                                threshold_value = threshold_value + 1
                                                alert_level = alert_level + 1

                                                if md_raw > threshold_value or md_raw < -threshold_value:
                                                    alert_level = alert_level + 1
                                            if alert_level == 1:
                                                print(f"\n橙色警报！")
                                            if alert_level == 2:
                                                print(f"\n红色警报！")
                                            if alert_level == 3:
                                                print(f"\n黄色警报！")
                                            cursor.execute(
                                                """INSERT INTO alert_records 
                                                (filtered_data_id, sensor_id, alert_level, alert_value, threshold_value, timestamp) 
                                                VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                                (filtered_data_id, sensor_id, alert_level, md_raw, threshold_value)
                                            )
                                            connection.commit()
                                            alert_level = alert_level_base


                                    # 3. 均值滤波
                                    mn_value, mn_raw = mean_filter(data_buffer[cmd])
                                    if mn_value:
                                        cursor.execute(
                                            """INSERT INTO filtered_data 
                                            (raw_data_id, sensor_id, filtered_value, filter_type, filter_params, receive_time) 
                                            VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                            (raw_data_id, sensor_id, mn_raw, "均值滤波", len(data_buffer[cmd]))
                                        )
                                        filtered_data_id = cursor.lastrowid
                                        connection.commit()
                                        print(f"均值滤波 :raw={mn_raw:7.2f}mm")
                                        if mn_raw > threshold_value or mn_raw < -threshold_value:
                                            threshold_value = threshold_value + 1
                                            alert_level = alert_level + 1

                                            if mn_raw > threshold_value or mn_raw < -threshold_value:
                                                threshold_value = threshold_value + 1
                                                alert_level = alert_level + 1

                                                if mn_raw > threshold_value or mn_raw < -threshold_value:
                                                    alert_level = alert_level + 1
                                            if alert_level == 1:
                                                print(f"\n橙色警报！")
                                            if alert_level == 2:
                                                print(f"\n红色警报！")
                                            if alert_level == 3:
                                                print(f"\n黄色警报！")
                                            cursor.execute(
                                                """INSERT INTO alert_records 
                                                (filtered_data_id, sensor_id, alert_level, alert_value, threshold_value, timestamp) 
                                                VALUES (%s, %s, %s, %s, %s, NOW(3))""",
                                                (filtered_data_id, sensor_id, alert_level, mn_raw, threshold_value)
                                            )
                                            connection.commit()


                                print(f"温度 :{T:7.1f}°C")

                                # 更新数据缓存
                                data_buffer[cmd].append((M, raw))
                                if len(data_buffer[cmd]) > BUFFER_SIZE:
                                    data_buffer[cmd].pop(0)



                        except ValueError as e:
                            print(f"[{position}] 数据处理错误: {e}")



                except socket.timeout:
                    print(f"[{position}] 等待响应超时，未收到回复")

                if cmd != COMMANDS[-1]:
                    time.sleep(COMMAND_INTERVAL)



            time.sleep(ROUND_INTERVAL - (len(COMMANDS) - 1) * COMMAND_INTERVAL)

    except KeyboardInterrupt:
        print("\n客户端被用户中断")

    finally:
        sock.close()
        if connection and connection.is_connected():
            connection.close()
            print("数据库连接已关闭")
        print("UDP连接已关闭")


if __name__ == '__main__':
    udp_client()